import { newMonkeyError } from "./evaluator.js";
import { 
    MonkeyArray, 
    MonkeyBuiltin, 
    MonkeyError, 
    MonkeyInteger, 
    MonkeyNull, 
    MonkeyObjectType, 
    MonkeyString 
} from "./object.js";

const singleNull = new MonkeyNull();

export const builtins = {
    len: new MonkeyBuiltin((...args) => {
        if (args.length > 1) {
            return newMonkeyError(
                `wrong number of arguments. got=${args.length}, want=1`
            )
        }
        if (args[0] instanceof MonkeyString) {
            return new MonkeyInteger(args[0].value.length)
        } else if (args[0] instanceof MonkeyArray) {
            return new MonkeyInteger(args[0].elements.length)
        } else {
            return newMonkeyError(
                'argument to `len` not supported, got ' + args[0].type()
            )
        }
    }),
    first: new MonkeyBuiltin((...args) => {
        if (args.length > 1) {
            return new MonkeyError(`wrong number of arguments. got=${args.length}, want=1`);
        }
        if (args[0].type() !== MonkeyObjectType.ARRAY) {
            return new MonkeyError(`argument to first must be Array, got ${args[0].type()}`)
        }
        if (args[0].elements.length > 0) {
            return args[0].elements[0];
        }
        return singleNull;
    }),
    last: new MonkeyBuiltin((...args) => {
        if (args.length > 1) {
            return new MonkeyError(`wrong number of arguments. got=${args.length}, want=1`);
        }
        if (args[0].type() !== MonkeyObjectType.ARRAY) {
            return new MonkeyError(`argument to first must be Array, got ${args[0].type()}`)
        }
        if (args[0].elements.length > 0) {
            return args[0].elements[args[0].elements.length - 1];
        }
        return singleNull;
    }),
    rest: new MonkeyBuiltin((...args) => {
        if (args.length > 1) {
            return new MonkeyError(`wrong number of arguments. got=${args.length}, want=1`);
        }
        if (args[0].type() !== MonkeyObjectType.ARRAY) {
            return new MonkeyError(`argument to first must be Array, got ${args[0].type()}`)
        }
        const len = args[0].elements.length;
        if (len > 0) {
            const newElements = [];
            for (let i = 1; i < len; i++) {
                newElements.push(args[0].elements[i]);
            }
            return new MonkeyArray(newElements);
        }
        return singleNull;
    }),
    push: new MonkeyBuiltin((...args) => {
        if (args.length !==2) {
            return new MonkeyError(`wrong number of arguments. got=${args.length}, want=2`);
        }
        if (args[0].type() !== MonkeyObjectType.ARRAY) {
            return new MonkeyError(`argument to first must be Array, got ${args[0].type()}`)
        }
        const len = args[0].elements.length;
        if (len > 0) {
            const newElements = [];
            for (let i = 0; i < len; i++) {
                newElements.push(args[0].elements[i]);
            }
            newElements.push(args[1]);
            return new MonkeyArray(newElements);
        }
        return singleNull;
    }),
}